package com.capgemini.gae.daos;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import com.google.appengine.api.datastore.Key;

public abstract class Dao<T extends PersistableObject> {
	/**
	 * Searches the object with matching id, will return the requested object or
	 * null.
	 * 
	 * @param id
	 * @return
	 */
	public T load(Class entityClass, Key id) {
		EntityManager em = EntityManagerFactoryHolder.get()
				.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		T type = null;
		try {
			tx.begin();
			type = (T) em.find(entityClass, id);
			tx.commit();
		} finally {
			if (tx.isActive()) {
				tx.rollback();
			}
			em.close();
		}

		return type;
	}

	/**
	 * Update an already existing row or insert when not yet in database.
	 * 
	 * @param type
	 */
	public T save(T type) {
		EntityManager em = EntityManagerFactoryHolder.get()
				.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		PersistableObject temp = null;
		try {
			tx.begin();
			if ((type.getId() != null)) {
				temp = em.find(type.getEntityClass(), type.getKey());
			}
			if (temp == null) {
				// if id not already in database
				em.persist(type);
			} else {
				// if previous version already in database
				type = em.merge(type);
			}

			tx.commit();

			return type;
		} finally {
			if (tx.isActive()) {
				tx.rollback();
			}

			em.close();
		}
	}

	@SuppressWarnings("unchecked")
	public void delete(T type) {
		EntityManager em = EntityManagerFactoryHolder.get()
				.createEntityManager();

		EntityTransaction tx = em.getTransaction();

		try {
			tx.begin();
			type = (T) em.find(type.getEntityClass(), type.getKey());
			em.remove(type);
			tx.commit();
		} finally {
			if (tx.isActive()) {
				tx.rollback();
			}

			em.close();
		}
	}
}
